package com.example.teaching_server.service;

import com.example.teaching_server.dto.CreateActivityRequest;
import com.example.teaching_server.dto.ScheduleDTO;
import com.example.teaching_server.entity.*;
import com.example.teaching_server.repository.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 课程表管理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class ScheduleService {

    private final ScheduleRepository scheduleRepository;
    private final TimeSlotRepository timeSlotRepository;
    private final TermRepository termRepository;
    private final ClassRepository classRepository;
    private final TeacherRepository teacherRepository;
    private final ClassroomRepository classroomRepository;
    private final CourseRepository courseRepository;

    /**
     * 获取教师班级课程表
     */
    @Transactional(readOnly = true)
    public List<ScheduleDTO> getTeacherClassScheduleByDateRange(
            Long teacherId, Long classId, LocalDate startDate, LocalDate endDate) {

        log.debug("查询教师班级课程表: teacherId={},classId={},startDate={},endDate={}",
                teacherId, classId, startDate, endDate);

        List<ScheduleEntity> schedules = scheduleRepository.findByTeacherClassAndDateRange(
                teacherId, classId, startDate, endDate);

        return schedules.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 获取班级课程表
     */
    @Transactional(readOnly = true)
    public List<ScheduleDTO> getClassScheduleByDateRange(Long classId, LocalDate startDate, LocalDate endDate) {
        log.debug("查询班级课程表: classId={},startDate={},endDate={}", classId, startDate, endDate);

        List<ScheduleEntity> schedules = scheduleRepository.findByClassIdAndDateRange(classId, startDate, endDate);

        return schedules.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 获取学生课程表
     */
    @Transactional(readOnly = true)
    public List<ScheduleDTO> getStudentScheduleByDateRange(Long classId, LocalDate startDate, LocalDate endDate) {
        log.debug("查询学生课程表: classId={},startDate={},endDate={}", classId, startDate, endDate);
        return getClassScheduleByDateRange(classId, startDate, endDate);
    }

    /**
     * 创建活动
     */
    public ScheduleDTO createActivity(CreateActivityRequest request) {
        log.info("创建活动: activityName={},classId={},teacherId={}",
                request.getActivityName(), request.getClassId(), request.getTeacherId());

        checkScheduleConflict(request);
        ScheduleEntity activity = buildActivityEntity(request);
        ScheduleEntity savedActivity = scheduleRepository.save(activity);

        return convertToDTO(savedActivity);
    }

    /**
     * 调整课程时间
     */
    public void rescheduleWithTimeSlot(Long scheduleId, LocalDate newDate, Long timeSlotId) {
        log.info("调整课程时间: scheduleId={},newDate={},timeSlotId={}", scheduleId, newDate, timeSlotId);

        ScheduleEntity schedule = scheduleRepository.findById(scheduleId)
                .orElseThrow(() -> new RuntimeException("课程安排不存在"));

        TimeSlotEntity timeSlot = timeSlotRepository.findById(timeSlotId)
                .orElseThrow(() -> new RuntimeException("时间节次不存在"));

        schedule.setSpecificDate(newDate);
        schedule.setWeekDay(getWeekDayNumber(newDate));
        schedule.setTimeSlot(timeSlot);

        scheduleRepository.save(schedule);
    }

    /**
     * 检查时间冲突
     */
    private void checkScheduleConflict(CreateActivityRequest request) {
        // 检查场地冲突
        boolean classroomConflict = scheduleRepository.existsBySpecificDateAndTimeSlotAndClassroom(
                request.getSpecificDate(),
                request.getTimeSlotId(),
                request.getClassroomId()
        );

        if (classroomConflict) {
            throw new RuntimeException("该场地在目标时间已被占用");
        }

        // 检查教师冲突
        boolean teacherConflict = scheduleRepository.existsBySpecificDateAndTimeSlotAndTeacher(
                request.getSpecificDate(),
                request.getTimeSlotId(),
                request.getTeacherId()
        );

        if (teacherConflict) {
            throw new RuntimeException("教师在该时间已有其他安排");
        }

        // 检查班级冲突
        boolean classConflict = scheduleRepository.existsBySpecificDateAndTimeSlotAndClass(
                request.getSpecificDate(),
                request.getTimeSlotId(),
                request.getClassId()
        );

        if (classConflict) {
            throw new RuntimeException("班级在该时间已有其他课程");
        }
    }

    /**
     * 构建活动实体
     */
    private ScheduleEntity buildActivityEntity(CreateActivityRequest request) {
        ScheduleEntity activity = new ScheduleEntity();

        // 设置基本信息
        activity.setSpecificDate(request.getSpecificDate());
        activity.setWeekDay(getWeekDayNumber(request.getSpecificDate()));
        activity.setWeekNumber(calculateWeekNumber(request.getSpecificDate(), request.getTermId()));
        activity.setDisplayName(request.getActivityName());
        activity.setActivityType(ScheduleEntity.ActivityType.ACTIVITY);

        // 设置关联实体
        activity.setTerm(getEntityById(termRepository, request.getTermId(), "学期"));
        activity.setTimeSlot(getEntityById(timeSlotRepository, request.getTimeSlotId(), "时间节次"));
        activity.setClassEntity(getEntityById(classRepository, request.getClassId(), "班级"));
        activity.setTeacher(getEntityById(teacherRepository, request.getTeacherId(), "教师"));
        activity.setClassroom(getEntityById(classroomRepository, request.getClassroomId(), "场地"));

        // 创建或获取课程信息
        CourseEntity course = createOrGetCourseForActivity(request);
        activity.setCourse(course);

        return activity;
    }

    /**
     * 创建或获取课程信息
     */
    private CourseEntity createOrGetCourseForActivity(CreateActivityRequest request) {
        Optional<CourseEntity> existingCourse = courseRepository.findByCourseName(request.getActivityName());

        if (existingCourse.isPresent()) {
            return existingCourse.get();
        } else {
            CourseEntity newCourse = new CourseEntity();
            newCourse.setCourseName(request.getActivityName());
            newCourse.setCategory(request.getCategory());
            return courseRepository.save(newCourse);
        }
    }

    /**
     * 通用实体获取方法
     */
    private <T> T getEntityById(JpaRepository<T, Long> repository, Long id, String entityName) {
        return repository.findById(id)
                .orElseThrow(() -> new RuntimeException(entityName + "不存在"));
    }

    /**
     * 计算星期几（1=周一,2=周二,...,7=周日）
     */
    private Integer getWeekDayNumber(LocalDate date) {
        int dayOfWeek = date.getDayOfWeek().getValue();
        return dayOfWeek == 7 ? 0 : dayOfWeek;
    }

    /**
     * 计算周次
     */
    private Integer calculateWeekNumber(LocalDate specificDate, Long termId) {
        TermEntity term = termRepository.findById(termId)
                .orElseThrow(() -> new RuntimeException("学期不存在"));

        long weeksBetween = ChronoUnit.WEEKS.between(
                term.getStartDate().atStartOfDay(),
                specificDate.atStartOfDay()
        );

        return (int) weeksBetween + 1;
    }

    /**
     * DTO转换方法
     */
    private ScheduleDTO convertToDTO(ScheduleEntity entity) {
        ScheduleDTO dto = new ScheduleDTO();
        dto.setScheduleId(entity.getScheduleId());
        dto.setWeekNumber(entity.getWeekNumber());
        dto.setSpecificDate(entity.getSpecificDate());

        // 转换Term
        if (entity.getTerm() != null) {
            ScheduleDTO.TermDTO termDTO = new ScheduleDTO.TermDTO();
            termDTO.setTermId(entity.getTerm().getTermId());
            termDTO.setTermName(entity.getTerm().getTermName());
            termDTO.setStartDate(entity.getTerm().getStartDate().toString());
            termDTO.setEndDate(entity.getTerm().getEndDate().toString());
            termDTO.setIsCurrent(entity.getTerm().getIsCurrent());
            dto.setTerm(termDTO);
        }

        // 转换TimeSlot
        if (entity.getTimeSlot() != null) {
            ScheduleDTO.TimeSlotDTO timeSlotDTO = new ScheduleDTO.TimeSlotDTO();
            timeSlotDTO.setSlotId(entity.getTimeSlot().getSlotId());
            timeSlotDTO.setSlotName(entity.getTimeSlot().getSlotName());
            timeSlotDTO.setStartTime(entity.getTimeSlot().getStartTime());
            timeSlotDTO.setEndTime(entity.getTimeSlot().getEndTime());
            timeSlotDTO.setSortOrder(entity.getTimeSlot().getSortOrder());
            dto.setTimeSlot(timeSlotDTO);
        }

        // 转换Class
        if (entity.getClassEntity() != null) {
            ScheduleDTO.ClassDTO classDTO = new ScheduleDTO.ClassDTO();
            classDTO.setClassId(entity.getClassEntity().getClassId());
            classDTO.setClassName(entity.getClassEntity().getClassName());

            // 修改这里：使用getGradeId()快捷方法
            classDTO.setGradeId(entity.getClassEntity().getGradeId());

            dto.setClassInfo(classDTO);
        }

        // 转换Course
        if (entity.getCourse() != null) {
            ScheduleDTO.CourseDTO courseDTO = new ScheduleDTO.CourseDTO();
            courseDTO.setCourseId(entity.getCourse().getCourseId());
            courseDTO.setCourseName(entity.getCourse().getCourseName());
            courseDTO.setCategory(entity.getCourse().getCategory());
            courseDTO.setCredit(entity.getCourse().getCredit());
            dto.setCourse(courseDTO);
        }

        // 转换Teacher
        if (entity.getTeacher() != null) {
            ScheduleDTO.TeacherDTO teacherDTO = new ScheduleDTO.TeacherDTO();
            teacherDTO.setTeacherId(entity.getTeacher().getTeacherId());
            teacherDTO.setTeacherName(entity.getTeacher().getTeacherName());
            teacherDTO.setTitle(entity.getTeacher().getTitle());
            teacherDTO.setSpecialty(entity.getTeacher().getSpecialty());
            dto.setTeacher(teacherDTO);
        }

        // 转换Classroom
        if (entity.getClassroom() != null) {
            ScheduleDTO.ClassroomDTO classroomDTO = new ScheduleDTO.ClassroomDTO();
            classroomDTO.setClassroomId(entity.getClassroom().getClassroomId());
            classroomDTO.setRoomNumber(entity.getClassroom().getRoomNumber());
            classroomDTO.setBuilding(entity.getClassroom().getBuilding());
            classroomDTO.setCapacity(entity.getClassroom().getCapacity());
            dto.setClassroom(classroomDTO);
        }

        // 设置显示名称
        dto.setActivityType(entity.getActivityType().name());
        dto.setDisplayName(generateDisplayName(entity));

        return dto;
    }

    /**
     * 生成显示名称
     */
    private String generateDisplayName(ScheduleEntity entity) {

        return switch (entity.getActivityType()) {
            case COURSE -> entity.getCourse() != null ? entity.getCourse().getCourseName() : "课程";
            case MEETING -> "班会";
            case EXAM -> (entity.getCourse() != null ? entity.getCourse().getCourseName() : "课程") + "考试";
            case ACTIVITY -> "特别活动";
        };
    }
}
